#!/usr/bin/env python3
# -*- coding: utf-8 -*-
###----------1、文件说明----------###
'''
* 说明：文件更名程序
* 时间：2024-11-02 15:57:27
* 文件：
* 作者：Smile
* 版本：0.1
* 备注：
'''
import os, sys
from PySide2.QtCore import QPoint, QRect, QSize, Qt
from PySide2.QtWidgets import QMainWindow, QApplication, QWidget
from PySide2.QtWidgets import QLineEdit, QPushButton, QTextEdit, QCheckBox, QLabel
from PySide2.QtWidgets import QHBoxLayout, QVBoxLayout, QLayout
from PySide2.QtWidgets import QSizePolicy
# 文件选择函数所需要的库
from PySide2.QtWidgets import QFileDialog,QDialog
import qdarkstyle
from qdarkstyle import LightPalette # 颜色主题
import pywinstyles  # 窗口样式
import qtawesome as qta # 图标库
from loguru import logger as log
from pprint import pprint
import json,uuid

class FlowLayout(QLayout):
    def __init__(self, parent=None, margin=0, spacing=-1):
        # 初始化 FlowLayout，设置父对象、边距和间距
        super(FlowLayout, self).__init__(parent)

        if parent is not None:
            # 如果有父对象，设置内容边距
            self.setContentsMargins(margin, margin, margin, margin)
        # 设置布局项之间的间距
        self.setSpacing(spacing)
        # 初始化布局项列表
        self.itemList = []

    def __del__(self):
        # 析构函数，用于清理布局项
        item = self.takeAt(0)
        while item:
            item = self.takeAt(0)

    def addItem(self, item):
        # 添加布局项到列表
        self.itemList.append(item)

    def count(self):
        # 返回布局项的数量
        return len(self.itemList)

    def itemAt(self, index):
        # 根据索引返回布局项
        if index >= 0 and index < len(self.itemList):
            return self.itemList[index]

        return None

    def takeAt(self, index):
        # 根据索引移除并返回布局项
        if index >= 0 and index < len(self.itemList):
            return self.itemList.pop(index)

        return None

    def expandingDirections(self):
        # 返回布局扩展的方向，FlowLayout 不扩展
        return Qt.Orientations(Qt.Orientation(0))

    def hasHeightForWidth(self):
        # 表示布局的高度依赖于宽度
        return True

    def heightForWidth(self, width):
        # 计算给定宽度下的布局高度
        height = self.doLayout(QRect(0, 0, width, 0), True)
        return height

    def setGeometry(self, rect):
        # 设置布局的几何形状，并调用 doLayout 进行布局
        super(FlowLayout, self).setGeometry(rect)
        self.doLayout(rect, False)

    def sizeHint(self):
        # 返回布局的理想大小
        return self.minimumSize()

    def minimumSize(self):
        # 计算布局的最小尺寸
        size = QSize()
        for item in self.itemList:
            size = size.expandedTo(item.minimumSize())
        margin, _, _, _ = self.getContentsMargins()
        size += QSize(2 * margin, 2 * margin)
        return size

    def doLayout(self, rect, testOnly: bool):
        # 执行布局逻辑
        x = rect.x()
        y = rect.y()
        isAtFisrstRow = True
        item_rects = []

        for i, item in enumerate(self.itemList):
            wid = item.widget()
            # 获取水平和垂直布局间距
            style_layoutspacing_h = wid.style().layoutSpacing(QSizePolicy.Frame, QSizePolicy.Frame, Qt.Horizontal)
            spaceX = self.spacing() + style_layoutspacing_h
            style_layoutspacing_v = wid.style().layoutSpacing(QSizePolicy.Frame, QSizePolicy.Frame, Qt.Vertical)
            spaceY = self.spacing() + style_layoutspacing_v
            # 计算边距
            spaceSide = abs(rect.width() - (rect.width() // wid.width()) * wid.width() - (
                        rect.width() // wid.width() - 1) * spaceX) // 2

            if isAtFisrstRow:
                # 处理第一行的布局
                if len(item_rects) == 0:
                    x += spaceSide
                current_item_rect = QRect(QPoint(x, y), item.sizeHint())
                item_rects.append(current_item_rect)
                if not testOnly:
                    item.setGeometry(current_item_rect)
                next_x = current_item_rect.right() + spaceX
                x = next_x
                if next_x + current_item_rect.width() > rect.right():
                    isAtFisrstRow = False
            else:
                # 处理后续行的布局
                shortest_item_rect = min(item_rects, key=lambda item_rect: item_rect.height())
                x = shortest_item_rect.x()
                y = shortest_item_rect.bottom() + spaceY
                current_item_rect = QRect(QPoint(x, y), item.sizeHint())
                item_rects.remove(shortest_item_rect)
                item_rects.append(QRect(shortest_item_rect.topLeft(), current_item_rect.bottomRight()))
                if not testOnly:
                    item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
        if len(item_rects) > 0:
            # 返回布局的最大高度
            return max(item_rects, key=lambda x: x.height()).height()
        else:
            return 0


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setWindowTitle("界面例程")
        self.setStyleSheet(qdarkstyle.load_stylesheet(qt_api='pyqt5', palette=LightPalette())  )
        # 初始化配置文件
        self.initConfig("renameFileSettings.json")
        self.initGUI()
        self.setWindowIcon(qta.icon('fa5s.yin-yang', color='brown', color_active='orange'))



    def initConfig(self, path="settings.json"):
        '''初始化配置文件'''
        if os.path.exists(path):
            with open(path, "r", encoding="utf-8") as f:
                self.settings = json.load(f)
        else:
            self.settings = {
                "plan" : {}
            }

    def saveConfig(self, path="settings.json"):
        '''保存配置文件'''
        with open(path, "w", encoding="utf-8") as f:
            json.dump(self.settings, f, ensure_ascii=False, indent=4)

    def initGUI(self):
        self.widget =  QWidget(self)
        layout = QVBoxLayout(self.widget)
        # 第一行
        self.lineedit = QLineEdit(self.widget)
        self.pathselect = QPushButton("选择目录", self.widget)
        self.pathselect.clicked.connect(self.pathselectCallback)
        self.fileselect = QPushButton("选择文件", self.widget)
        self.fileselect.clicked.connect(self.fileselectCallback)
        linelayout = QHBoxLayout(self.widget)
        linelayout.addWidget(self.lineedit)
        linelayout.addWidget(self.fileselect)
        linelayout.addWidget(self.pathselect)
        layout.addLayout(linelayout)

        # 选择行
        self.checklayout = FlowLayout()
        for key in self.settings["plan"].keys():
            checkbox = QCheckBox(self.widget)
            name = '从"' + self.settings["plan"][key][0] + '"到"' + self.settings["plan"][key][1] + '"'
            checkbox.setText(name)
            checkbox.setObjectName(key)
            self.checklayout.addWidget(checkbox)
        layout.addLayout(self.checklayout)

        # 添加行
        addlayout = QHBoxLayout(self.widget)
        addlayout.addWidget(QLabel("从"))
        self.srclineedit = QLineEdit(self.widget)
        addlayout.addWidget(self.srclineedit)
        addlayout.addWidget(QLabel("替换为"))
        self.dstlineedit = QLineEdit(self.widget)
        addlayout.addWidget(self.dstlineedit)
        self.addplan = QPushButton("添加")
        addlayout.addWidget(self.addplan)
        self.addplan.clicked.connect(self.addplanCallback)
        layout.addLayout(addlayout)

        # 第二行
        self.textedit = QTextEdit(self.widget)

        layout.addWidget(self.textedit)
        # 第三行
        self.startbutton = QPushButton("运行程序", self.widget)
        layout.addWidget(self.startbutton)
        # 设置主要显示区
        self.setCentralWidget(self.widget)

        self.startbutton.clicked.connect(self.run)

    def fileSelect(self, filemode=0):
        '''
        filemode: 0-文件的名称，无论它是否存在 1-单文件模式 2-目录模型 3-多文件模式
        '''
        fileNames = []
        fileDialog = QFileDialog(self)
        fileDialog.setViewMode(QFileDialog.Detail)

        if filemode == 1:
            fileDialog.setFileMode(QFileDialog.ExistingFile)
        elif filemode == 2:
            fileDialog.setFileMode(QFileDialog.Directory)
        elif filemode == 3:
            fileDialog.setFileMode(QFileDialog.ExistingFiles)
        else:
            fileDialog.setFileMode(QFileDialog.AnyFile)

        fileDialog.setNameFilter("file(*.*);;all file(*)")
        ret = fileDialog.exec_()
        if ret == QDialog.Accepted:
            fileNames = fileDialog.selectedFiles()
        return fileNames

    def fileselectCallback(self, evt):
        print(self.lineedit.text())
        self.path = self.fileSelect(filemode=3)
        self.lineedit.setText(str(self.path))
        print(self.path)

    def pathselectCallback(self, evt):
        print(self.lineedit.text())
        self.path = self.fileSelect(filemode=2)
        self.lineedit.setText(str(self.path))
        print(self.path)

    def addplanCallback(self, evt):
        print(str(uuid.uuid4()))
        if self.srclineedit.text() not in self.settings["plan"].keys():
            key = str(uuid.uuid4())
            checkbox = QCheckBox(self.widget)
            self.settings["plan"][key] = [self.srclineedit.text(), self.dstlineedit.text()]
            name = '从"' + self.srclineedit.text() + '"到"' + self.dstlineedit.text() + '"'
            checkbox.setText(name)
            checkbox.setObjectName(key)
            self.checklayout.addWidget(checkbox)

        pprint(self.settings)
        self.saveConfig("renameFileSettings.json")

    def run(self):
        log.info("Start Program")
        for path in self.path:
            if os.path.isdir(path):
                # 遍历所有文件
                for root, dirs, files in os.walk(path):
                    for file in files:
                        src = file
                        dst = file

                        # 获取所有规则
                        for key,value in self.settings["plan"].items():
                            print(key,value)
                            for widget in self.widget.children():
                                if key == widget.objectName():
                                    print(widget.objectName, widget.text())
                                    if not widget.isChecked():
                                        break
                                    dst = dst.replace(value[0], value[1])
                                    print(dst)
                        print("原始文件", src)
                        print("目标文件", dst)
                        self.textedit.append("原始文件：" + os.path.join(root, src))
                        self.textedit.append("目标文件：" + os.path.join(root, dst))
                        os.rename(os.path.join(root, src), os.path.join(root, dst))


            if os.path.isfile(path):
                pass

if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWin = MainWindow()
    pywinstyles.apply_style(mainWin, "win7")
    mainWin.show()
    sys.exit(app.exec_())
